package com.example.jianzhioffer;

/**
 * Created by Quincy on 2018/9/13.
 * 输入一棵二叉搜索树，将其转换为一个排序的双向链表。
 * 要求：不能创建任何新的结点，只能调整树中结点指针的指向。
 */
public class BST2List {
    public class TreeNode {
        int val = 0;
        TreeNode left = null;
        TreeNode right = null;

        public TreeNode(int val) {
            this.val = val;
        }
    }

    /**
     * 二叉搜索树的特性是，其中序遍历是有序的，同时左子树的元素都比根结点小，右子树的元素都比根节点大。
     * 由上述特性可知，把二叉搜索树转换成双向链表后，根节点的前一个元素是左子树的最右边结点，根结点的后一个元素是右子树的最左边结点。
     * 左子树和右子树的转换过程是一样的，所以是一个递归的过程。
     * 注意，转换后返回的是指向双向链表的头指针。
     * */
    public TreeNode Convert(TreeNode pRootOfTree) {
        // 根节点为空
        if(pRootOfTree == null) return null;

        if(pRootOfTree.left != null){
            // 先转换左子树，获得转换后的头指针
            TreeNode left = Convert(pRootOfTree.left);

            // 获得指向左子树的最后一个元素的指针
            while(left.right != null) left = left.right;

            // 与root链接，注意双向
            pRootOfTree.left = left;
            left.right = pRootOfTree;
        }

        if(pRootOfTree.right != null){
            // 同理，转换右子树
            TreeNode right = Convert(pRootOfTree.right);

            // 获得指向右子树的第一个元素的指针，这里直接就是right，与root双向链接
            pRootOfTree.right = right;
            right.left = pRootOfTree;
        }

        // 最后把pRootOfTree指向双向链表的第一个元素再返回
        while(pRootOfTree.left != null){
            pRootOfTree = pRootOfTree.left;
        }

        return pRootOfTree;
    }
}
